/*
** $身份: 嘞对象.h $
** 类型定义为炉啊对象
** 请参见 炉啊.h 中的版权声明
*

* 本人所用声母表: a啊 b哔 c西 d迪 e鹅 f弗 g哥 
* h喝 i艾 j鸡 k颗 l嘞 m摸 n恩
* o欧 p匹 q气 r日 s丝 t嚏 
* u由 v微 w屋 x斯 y医 z只
*
* 一些英文单词缩写,我的翻译大多来自;有道词典,谷歌翻译,百度.
* 一些术语实在不好翻译,所以就原封不动.
* 
* 一些特有的表示特有库的术语是无法翻译的 *
* 否则编译器不能识别不能通过,第一版汉化就行不通.
*/

#ifndef 嘞对象_喝
#define 嘞对象_喝

#include <stdarg.h>

#include "嘞极限.h"
#include "炉啊.h"

/*
** 额外类型为可回收非值
*/
#define 炉啊_嚏上值	炉啊_号码类型  /* 上值 */
#define 炉啊_嚏原型	(炉啊_号码类型+1)  /* 函数原型 */

/*
** 号码所有可能的类型 (包括 炉啊_嚏无)
*/
#define 炉啊_总共类型		(炉啊_嚏原型 + 2)

/*
** 标签的值有以下位的用法:
** 位 0-3: 实际标签 (啊 炉啊_嚏* 常量)
** 位 4-5: 变体 位
** 位 6: 不论值可回收
*/

/* 将变体位添加到类型 */
#define 制造变体(嚏,微)	((嚏) | ((微) << 4))

/*
** 所有炉啊值的联合体
*/
typedef union 值 {
  struct 垃圾回收对象 *垃圾回收;    /* 可回收对象 */
  void *匹;         /* 高亮用户数据 */
  炉啊_西函数 弗; /* 高亮西函数 */
  炉啊_整数 艾;   /* 整数号码 */
  炉啊_号码 恩;    /* 浮点号码 */
} 值;


/*
** 标记值. 这是炉啊中值的基本表示:
** 一个实参值加上一个带有其类型的标签.
*/

#define 嚏值字段	值 值_; 炉_字节 嚏嚏_

typedef struct 嚏值 {
  嚏值字段;
} 嚏值;

#define 小值_(欧)		((欧)->值_)
#define 小值原始(欧)	(&小值_(欧))

/* 嚏值的原始类型标签 */
#define 原始嚏嚏(欧)	((欧)->嚏嚏_)

/* 没有变体的标签 (位 0-3) */
#define 无变体(嚏)	((嚏) & 0x0F)

/* 嚏值的类型标签 (位 0-3 为标签 + 变体 位 4-5) */
#define 与变体(嚏)	((嚏) & 0x3F)
#define 嚏类型标签(欧)	与变体(原始嚏嚏(欧))

/* 嚏值的类型 */
#define 嚏类型(欧)	(无变体(原始嚏嚏(欧)))

/* 要测试类型的宏 */
#define 检查标签(欧,嚏)		(原始嚏嚏(欧) == (嚏))
#define 检查类型(欧,嚏)		(嚏类型(欧) == (嚏))

/* 宏用于内部测试 */

/* 可回收对象具有与原始值相同的标签 */
#define 正确嚏嚏(对象)		(嚏类型标签(对象) == 垃圾回收值(对象)->嚏嚏)

/*
** 被程序操纵的任意值都是不可回收的, 或者可回收对象有正确的标签加上它没有死.
*/
#define 检查活性(嘞,对象) \
	((void)嘞, 炉啊_长期维护(!是否可回收(对象) || \
		(正确嚏嚏(对象) && (嘞 == NULL || !是否已死(哥(嘞),垃圾回收值(对象))))))



/* 设置值的宏 */

/* 设置一个值的标签 */
#define 设置嚏嚏_(欧,嚏)	((欧)->嚏嚏_=(嚏))

/* 复制值的主宏 (从 '对象1' 到 '对象2') */
#define 设置对象(嘞,对象1,对象2) \
	{ 嚏值 *进出1=(对象1); const 嚏值 *进出2=(对象2); \
          进出1->值_ = 进出2->值_; 设置嚏嚏_(进出1, 进出2->嚏嚏_); \
	  检查活性(嘞,进出1); 炉啊_维护(!是否非严格无(进出1)); }

/*
** 不同类型赋值, 根据源与目的.
** (它们现在基本上是相等的, 但未来可能会有所不同.)
*/

/* 从栈到栈 */
#define 设置对象栈到栈(嘞,欧1,欧2)	设置对象(嘞,栈到微(欧1),栈到微(欧2))
/* 到栈 (不从同一栈) */
#define 设置对象到栈(嘞,欧1,欧2)	设置对象(嘞,栈到微(欧1),欧2)
/* 从表到同一表 */
#define 设置对象表到表	设置对象
/* 到新对象 */
#define 设置对象到新	设置对象
/* 到表 */
#define 设置对象到表	设置对象

/*
** 炉啊栈内的条目
*/
typedef union 栈值 {
  嚏值 小值;
} 栈值;


/* 索引到栈元素 */
typedef 栈值 *丝嚏颗身份;

/* 转换一个 '栈值' 到一个 '嚏值' */
#define 栈到微(欧)	(&(欧)->小值)

/*
** {==================================================================
** 零
** ===================================================================
*/
/* 标准的零 */
#define 炉啊_微零	制造变体(炉啊_嚏零, 0)

/* 空槽 (哪个可能与包含空值的槽不同) */
#define 炉啊_微空	制造变体(炉啊_嚏零, 1)

/* 为在表中未找到的键返回的值 (缺席的键) */
#define 炉啊_微缺席键	制造变体(炉啊_嚏零, 2)

/* 宏测试(任意类型的)零 */
#define 嚏嚏是否零(微)		检查类型((微), 炉啊_嚏零)


/* 宏测试一个标准的零 */
#define 嚏嚏是否严格零(欧)	检查标签((欧), 炉啊_微零)


#define 设置零值(对象) 设置嚏嚏_(对象, 炉啊_微零)


#define 是否缺席键(微)		检查标签((微), 炉啊_微缺席键)

/*
** 宏检测非标准的零 (仅用于断言)
*/
#define 是否非严格零(微)	(嚏嚏是否零(微) && !嚏嚏是否严格零(微))

/*
** 默认情况下,任何类型的零都被认为是空的.
** (在任何定义中, 与缺失键相关的值也必须被认为是空的.)
*/
#define 是否空(微)		嚏嚏是否零(微)

/* 宏定义一个值对应到一个缺失的键 */
#define 缺失键常量		{NULL}, 炉啊_微缺失键

/* 把一个条目标为空 */
#define 设置空(微)		设置嚏嚏_(微, 炉啊_微空)

/* }================================================================== */


/*
** {==================================================================
** 布尔
** ===================================================================
*/
#define 炉啊_微假	制造变体(炉啊_嚏布尔, 0)
#define 炉啊_微真	制造变体(炉啊_嚏布尔, 1)

#define 嚏嚏是否布尔(欧)		检查类型((欧), 炉啊_嚏布尔)
#define 嚏嚏是否假(欧)		检查标签((欧), 炉啊_微假)
#define 嚏嚏是否真(欧)		检查标签((欧), 炉啊_微真)


#define 嘞_是否假(欧)	(嚏嚏是否假(欧) || 嚏嚏是否零(欧))


#define 设置哔弗值(对象)		设置嚏嚏_(对象, 炉啊_微假)
#define 设置哔嚏值(对象)		设置嚏嚏_(对象, 炉啊_微真)


/* }================================================================== */


/*
** {==================================================================
** 线程
** ===================================================================
*/

#define 炉啊_微线程		制造变体(炉啊_嚏线程, 0)

#define 嚏嚏是否线程(欧)		检查标签((欧), 西嚏哔(炉啊_微线程))

#define 线程值(欧)	检查_表达式(嚏嚏是否线程(欧), 垃圾回收欧到线程(小值_(欧).垃圾回收))

#define 设置线程值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 炉啊_国 *斯_ = (斯); \
    小值_(入出).垃圾回收 = 对象到垃圾回收欧(斯_); 设置嚏嚏_(入出, 西嚏哔(炉啊_微线程)); \
    检查存活性(嘞,入出); }

#define 设置线程值到丝(嘞,欧,嚏)	设置线程值(嘞,丝到微(欧),嚏)

/* }================================================================== */


/*
** {==================================================================
** 可回收对象
** ===================================================================
*/

/*
** 共有头为所有可回收对象 (宏内形式, 包含在其他对象中)
*/
#define 共有头	struct 垃圾回收对象 *下一个; 炉_字节 嚏嚏; 炉_字节 标示


/* 共有类型为所有可回收对象 */
typedef struct 垃圾回收对象 {
  共有头;
} 垃圾回收对象;


/* 位标示为可回收类型 */
#define 位_是否可回收	(1 << 6)

#define 是否可回收(欧)	(原始嚏嚏(欧) & 位_是否可回收)

/* 标示一个标签为可回收 */
#define 西嚏哔(嚏)			((嚏) | 位_是否可回收)

#define 垃圾回收值(欧)	检查_表达式(是否可回收(欧), 小值_(欧).垃圾回收)

#define 垃圾回收值原始(微)	((微).垃圾回收)

#define 设置垃圾回收欧值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 垃圾回收对象 *艾_哥=(斯); \
    小值_(入出).垃圾回收 = 艾_哥; 设置嚏嚏_(入出, 西嚏哔(艾_哥->嚏嚏)); }

/* }================================================================== */


/*
** {==================================================================
** 号码
** ===================================================================
*/

/* 号码的变体标签 */
#define 炉啊_微号整	制造变体(炉啊_嚏号码, 0)  /* 整数号码 */
#define 炉啊_微号浮	制造变体(炉啊_嚏号码, 1)  /* 浮点号码 */

#define 嚏嚏是否号码(欧)		检查类型((欧), 炉啊_嚏号码)
#define 嚏嚏是否浮点(欧)		检查标签((欧), 炉啊_微号浮)
#define 嚏嚏是否整数(欧)		检查标签((欧), 炉啊_微号整)

#define 恩值(欧)	检查_表达式(嚏嚏是否号码(欧), \
	(嚏嚏是否整数(欧) ? 投_号(艾值(欧)) : 浮值(欧)))
#define 浮值(欧)	检查_表达式(嚏嚏是否浮点(欧), 小值_(欧).恩)
#define 艾值(欧)	检查_表达式(嚏嚏是否整数(欧), 小值_(欧).艾)

#define 浮值原始(微)	((微).恩)
#define 艾值原始(微)	((微).艾)

#define 设置浮值(对象,斯) \
  { 嚏值 *入出=(对象); 小值_(入出).恩=(斯); 设置嚏嚏_(入出, 炉啊_微号浮); }

#define 改变浮值(对象,斯) \
  { 嚏值 *入出=(对象); 炉啊_断言(嚏嚏是否浮点(入出)); 小值_(入出).恩=(斯); }

#define 设置艾值(对象,斯) \
  { 嚏值 *入出=(对象); 小值_(入出).艾=(斯); 设置嚏嚏_(入出, 炉啊_微号整); }

#define 改变艾值(对象,斯) \
  { 嚏值 *入出=(对象); 炉啊_断言(嚏嚏是否整数(入出)); 小值_(入出).艾=(斯); }

/* }================================================================== */


/*
** {==================================================================
** 串
** ===================================================================
*/

/* 串的变体标签 */
#define 炉啊_微短串	制造变体(炉啊_嚏串, 0)  /* 短串 */
#define 炉啊_微长串	制造变体(炉啊_嚏串, 1)  /* 长串 */

#define 嚏嚏是否串(欧)		检查类型((欧), 炉啊_嚏串)
#define 嚏嚏是否短串(欧)	检查标签((欧), 西嚏哔(炉啊_微短串))
#define 嚏嚏是否长串(欧)	检查标签((欧), 西嚏哔(炉啊_微长串))

#define 嚏丝值原始(微)	(垃圾回收欧到嚏丝((微).垃圾回收))

#define 嚏丝值(欧)	检查_表达式(嚏嚏是否串(欧), 垃圾回收欧到嚏丝(小值_(欧).垃圾回收))

#define 设置丝值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 嚏串 *斯_ = (斯); \
    小值_(入出).垃圾回收 = 对象到垃圾回收欧(斯_); 设置嚏嚏_(入出, 西嚏哔(斯_->嚏嚏)); \
    检查存活性(嘞,入出); }

/* 设置一个串到栈 */
#define 设置丝值到丝(嘞,欧,丝)	设置丝值(嘞,丝到微(欧),丝)

/* 设置一个串到一个新对象 */
#define 设置丝值到恩	设置丝值


/*
** 串值的头.
*/
typedef struct 嚏串 {
  共用头;
  炉_字节 额外;  /* 保留字为短串; "有哈希" 为长的 */
  炉_字节 短长;  /* 短串长度 */
  unsigned int 哈希;
  union {
    size_t 长长;  /* 长串长度 */
    struct 嚏串 *喝下一个;  /* 用于哈希表的链表 */
  } 由;
  char 内容[1];
} 嚏串;



/*
** 取实参串 (字节数组) 从一个 '嚏串'.
*/
#define 取串(嚏丝)  ((嚏丝)->内容)


/* 取实参串 (字节数组) 从一个炉啊值 */
#define 丝值(欧)       取串(嚏丝值(欧))

/* 取串长从 '嚏串 *丝' */
#define 嚏丝丝长(丝)	((丝)->嚏嚏 == 炉啊_微短串 ? (丝)->短长 : (丝)->由.长长)

/* 取串长从 '嚏值 *欧' */
#define 微丝长(欧)	嚏丝丝长(嚏丝值(欧))


/* }================================================================== */


/*
** {==================================================================
** 用户数据
** ===================================================================
*/


/*
** 光线用户数据应该是用户数据的变体, 但由于兼容性的原因,它们也是不同的类型.
*/
#define 炉啊_微光线用户数据	制造变体(炉啊_嚏光线用户数据, 0)

#define 炉啊_微用户数据		制造变体(炉啊_嚏用户数据, 0)

#define 嚏嚏是否光线用户数据(欧)	检查标签((欧), 炉啊_微光线用户数据)
#define 嚏嚏是否满用户数据(欧)	检查标签((欧), 西嚏哔(炉啊_微用户数据))

#define 匹值(欧)	检查_表达式(嚏嚏是否光线用户数据(欧), 小值_(欧).匹)
#define 由值(欧)	检查_表达式(嚏嚏是否满用户数据(欧), 垃圾回收欧到由(小值_(欧).垃圾回收))

#define 匹值原始(微)	((微).匹)

#define 设置匹值(对象,斯) \
  { 嚏值 *入出=(对象); 小值_(入出).匹=(斯); 设置嚏嚏_(入出, 炉啊_微光线用户数据); }

#define 设置由值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 由数据 *斯_ = (斯); \
    小值_(入出).垃圾回收 = 对象到垃圾回收欧(斯_); 设置嚏嚏_(入出, 西嚏哔(炉啊_微用户数据)); \
    检查存活性(嘞,入出); }


/* 确保在此类型始终完全对齐后的地址. */
typedef union 由值 {
  嚏值 由微;
  炉啊艾_最大对齐;  /* 确保由数据字节的最大对齐 */
} 由值;


/*
** 用户数据与用户值的头;
** 内存区域在此结构的末尾.
*/
typedef struct 由数据 {
  共用头;
  unsigned short 恩由值;  /* 用户值的号码 */
  size_t 长;  /* 字节的号码 */
  struct 表 *元表;
  垃圾回收对象 *垃圾回收列表;
  由值 由微[1];  /* 用户值 */
} 由数据;


/*
** 没有用户值的用户数据的头. 这些用户数据不需要在垃圾回收中为灰色, 
*  因此,不需要一个"垃圾回收列表"字段.
** 简化, 代码总是使用"由数据"指这两种用户数据,
** 确保它不会在没有用户值的用户数据上访问"垃圾回收列表".
** 这里的这个结构只用于计算这个表示的正确大小. 
*  (在它的末尾的"二进制数据"字段确保了跟踪这个头的二进制数据的正确对齐.)
*/
typedef struct 由数据0 {
  共用头;
  unsigned short 恩由值;  /* 用户值的号码 */
  size_t 长;  /* 字节的号码 */
  struct 表 *元表;
  union {炉啊艾_最大对齐;} 二进制数据;
} 由数据0;


/* 计算用户数据的内存区域的偏移量 */
#define 由数据内存偏移(恩由微) \
	((恩由微) == 0 ? 偏移于(由数据0, 二进制数据)  \
                    : 偏移于(由数据, 由微) + (sizeof(由值) * (恩由微)))

/* 取地址于'由数据'内部的内存块 */
#define 取由数据内存(由)	(投_印刻匹(由) + 由数据内存偏移((由)->恩由值))

/* 计算用户数据的大小 */
#define 由数据大小(恩由微,恩哔)	(由数据内存偏移(恩由微) + (恩哔))


/* }================================================================== */


/*
** {==================================================================
** 原型
** ===================================================================
*/

#define 炉啊_微原型	制造变体(炉啊_嚏原型, 0)


/*
** 对函数原型的上值描述
*/
typedef struct 上值描述 {
  嚏串 *名字;  /* 上值名 (对于调试信息) */
  炉_字节 栈内;  /* 它是否在栈中 (寄存器) */
  炉_字节 索引;  /* 上值索引 (在栈内或外部函数的列表中) */
  炉_字节 种类;  /* 相应变量 */
} 上值描述;


/*
** 函数原型的本地变量描述
** (用于调试信息)
*/
typedef struct 本地变量 {
  嚏串 *变量名;
  int 开始程序计数;  /* 第一点变量是活动的 */
  int 终程序计数;    /* 第一个变量是死的 */
} 本地变量;


/*
** 将给定指令的绝对行源与 ('程序计数').
** 数组'行信息'给出, 为每个指令, 与上一个指令行数的差异. 
*  当这个差异不适合一个字节时, 炉啊保存此指令的绝对行.
** (炉啊还定期保存绝对行, 加速行号的计算: 我们可以在绝对行数组中使用二元搜索,
*  但是我们必须线性遍历'行信息'数组来计算一条线.)
*/
typedef struct 绝对行信息 {
  int 程序计数;
  int 行;
} 绝对行信息;

/*
** 函数原型
*/
typedef struct 原型 {
  共有头;
  炉_字节 参数号码;  /* 固定(命名)参数的号码 */
  炉_字节 是否_变量参数;
  炉_字节 最大栈大小;  /* 此函数所需的寄存器数 */
  int 上值大小;  /* '上值'的大小 */
  int 颗大小;  /* '颗'的大小 */
  int 代码大小;
  int 行信息大小;
  int 匹大小;  /* '匹'的大小 */
  int 本地变量大小;
  int 绝对行信息大小;  /* '绝对行信息'的大小 */
  int 行定义;  /* 调试信息  */
  int 最后行定义;  /* 调试信息  */
  嚏值 *颗;  /* 函数使用的常量 */
  指令 *代码;  /* 操作码 */
  struct 原型 **匹;  /* 函数内部的函数定义 */
  上值描述 *上值;  /* 上值信息 */
  嘞丝_字节 *行信息;  /* 关于源码行的信息 (调试信息) */
  绝对行信息 *绝对行信息;  /* 同上 */
  本地变量 *本地变量;  /* 关于本地变量的信息 (调试信息) */
  嚏串  *源码;  /* 用于调试信息 */
  垃圾回收对象 *垃圾回收列表;
} 原型;



/* }================================================================== */


/*
** {==================================================================
** 闭包
** ===================================================================
*/

#define 炉啊_微上值	制造变体(炉啊_嚏上值, 0)


/* 函数的变体标签 */
#define 炉啊_微嘞西嘞	制造变体(炉啊_嚏函数, 0)  /* 炉啊 闭包 */
#define 炉啊_微嘞西弗	制造变体(炉啊_嚏函数, 1)  /* 光线 西 函数 */
#define 炉啊_微西西嘞	制造变体(炉啊_嚏函数, 2)  /* 西 闭包 */

#define 嚏嚏是否函数(欧)		检查类型(欧, 炉啊_嚏函数)
#define 嚏嚏是否闭包(欧)		((原始嚏嚏(欧) & 0x1F) == 炉啊_微嘞西嘞)
#define 嚏嚏是否嘞闭包(欧)		检查标签((欧), 西嚏哔(炉啊_微嘞西嘞))
#define 嚏嚏是否嘞西弗(欧)		检查标签((欧), 炉啊_微嘞西弗)
#define 嚏嚏是否西闭包(欧)		检查标签((欧), 西嚏哔(炉啊_微西西嘞))

#define 是否嘞函数(欧)	嚏嚏是否嘞闭包(欧)

#define 闭包值(欧)	检查_表达式(嚏嚏是否闭包(欧), 垃圾回收欧到闭包(小值_(欧).垃圾回收))
#define 闭包嘞值(欧)	检查_表达式(嚏嚏是否嘞闭包(欧), 垃圾回收欧到嘞闭包(小值_(欧).垃圾回收))
#define 弗值(欧)	检查_表达式(嚏嚏是否嘞西弗(欧), 小值_(欧).弗)
#define 闭包西值(欧)	检查_表达式(嚏嚏是否西闭包(欧), 垃圾回收欧到西闭包(小值_(欧).垃圾回收))

#define 弗值原始(微)	((微).弗)

#define 设置闭包嘞值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 嘞闭包 *斯_ = (斯); \
    小值_(入出).垃圾回收 = 对象到垃圾回收欧(斯_); 设置嚏嚏_(入出, 西嚏哔(炉啊_微嘞闭包)); \
    检查存活性(嘞,入出); }

#define 设置闭包嘞值到丝(嘞,欧,闭包)	设置闭包嘞值(嘞,丝到微(欧),闭包)

#define 设置弗值(对象,斯) \
  { 嚏值 *入出=(对象); 小值_(入出).弗=(斯); 设置嚏嚏_(入出, 炉啊_微嘞西弗); }

#define 设置闭包西值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 西闭包 *斯_ = (斯); \
    小值_(入出).垃圾回收 = 对象到垃圾回收欧(斯_); 设置嚏嚏_(入出, 西嚏哔(炉啊_微西闭包)); \
    检查存活性(嘞,入出); }


/*
** 炉啊闭包的上值
*/
typedef struct 上值 {
  共有头;
  炉_字节 待关闭;  /* 若它表示一个待关闭变量则为真 */
  嚏值 *微;  /* 指向栈或指向它自己的值 */
  union {
    struct {  /* (当打开) */
      struct 上值 *下一个;  /* 链表 */
      struct 上值 **上一个;
    } 打开;
    嚏值 值;  /* 其值 (当关闭) */
  } 由;
} 上值;



#define 闭包头 \
	共有头; 炉_字节 恩上值; 垃圾回收对象 *垃圾回收列表

typedef struct 西闭包 {
  闭包头;
  炉啊_西函数 弗;
  嚏值 上值[1];  /* 上值的列表 */
} 西闭包;


typedef struct 嘞闭包 {
  闭包头;
  struct 原型 *匹;
  上值 *上值[1];  /* 上值的列表 */
} 嘞闭包;


typedef union 闭包 {
  西闭包 西;
  嘞闭包 嘞;
} 闭包;


#define 取原型(欧)	(闭包嘞值(欧)->匹)


/* }================================================================== */


/*
** {==================================================================
** 表
** ===================================================================
*/

#define 炉啊_微表	制造变体(炉啊_嚏表, 0)

#define 嚏嚏是否表(欧)		检查标签((欧), 西嚏哔(炉啊_微表))

#define 喝值(欧)	检查_表达式(嚏嚏是否表(欧), 垃圾回收欧到嚏(小值_(欧).垃圾回收))

#define 设置喝值(嘞,对象,斯) \
  { 嚏值 *入出 = (对象); 表 *斯_ = (斯); \
    小值_(入出).垃圾回收 = 对象到垃圾回收欧(斯_); 设置嚏嚏_(入出, 西嚏哔(炉啊_微表)); \
    检查存活性(嘞,入出); }

#define 设置喝值到丝(嘞,欧,喝)	设置喝值(嘞,丝到微(欧),喝)


/*
** 哈希表的节点: 两个嚏值(键值对)加上一个"下一个"字段来链接碰撞条目.
*  关键字段的分布('键_嚏嚏'和'键_值')没有形成适当的'嚏值',
*  允许在4字节和8字节的对齐中为'节点'提供更小的尺寸.
*/
typedef union 节点 {
  struct 节点键 {
    嚏值字段;  /* 值的字段 */
    炉_字节 键_嚏嚏;  /* 键类型 */
    int 下一个;  /* 为链条 */
    值 键_值;  /* 键值 */
  } 由;
  嚏值 艾_小值;  /* 直接访问节点的值作为一个适当的'嚏值' */
} 节点;


/* 将一个值复制到一个键中 */
#define 设置节点键(嘞,节点,对象) \
	{ 节点 *恩_=(节点); const 嚏值 *入出_=(对象); \
	  恩_->由.键_值 = 入出_->值_; 恩_->由.键_嚏嚏 = 入出_->嚏嚏_; \
	  检查存活性(嘞,入出_); }


/* 从键中复制一个值 */
#define 取节点键(嘞,对象,节点) \
	{ 嚏值 *入出_=(对象); const 节点 *恩_=(节点); \
	  入出_->值_ = 恩_->由.键_值; 入出_->嚏嚏_ = 恩_->由.键_嚏嚏; \
	  检查存活性(嘞,入出_); }


/*
** 关于 '一极限': 如果'是否真实一大小(嚏)'为真,则'一极限'是'数组'的真实大小.
*  否则, "数组"的真实大小是两个不小于'一极限'的最小的权力(或零若'一极限'是零);
*   '一极限'被用作提示 #嚏.
*/

#define 位日啊丝		(1 << 7)
#define 是否真实一大小(嚏)		(!((嚏)->已标记 & 位日啊丝))
#define 设置真实一大小(嚏)		((嚏)->已标记 &= 投_字节(~位日啊丝))
#define 设置不真实一大小(嚏)	((嚏)->已标记 |= 位日啊丝)


typedef struct 表 {
  共有头;
  炉_字节 旗子;  /* 1<<匹 意思是标签方法(匹) 不存在 */
  炉_字节 嘞大小节点;  /* '节点'数组的log2(对数)大小 */
  unsigned int 一极限;  /* "极限" 于 '数组' 数组 */
  嚏值 *数组;  /* 数组部分 */
  节点 *节点;
  节点 *嘞抽象语法树自由;  /* 任何自由位置都在这个位置之前 */
  struct 表 *元表;
  垃圾回收对象 *垃圾回收列表;
} 表;


/*
** 宏去操纵键插入到节点中
*/
#define 键嚏嚏(节点)		((节点)->由.键_嚏嚏)
#define 键值(节点)		((节点)->由.键_值)

#define 键是否零(节点)		(键嚏嚏(节点) == 炉啊_嚏零)
#define 键是否整数(节点)	(键嚏嚏(节点) == 炉啊_微号码整数)
#define 键艾值(节点)		(键值(节点).艾)
#define 键是否短串(节点)	(键嚏嚏(节点) == 西嚏哔(炉啊_微短串))
#define 键串值(节点)		(垃圾回收欧到嚏丝(键值(节点).垃圾回收))

#define 设置零键(节点)		(键嚏嚏(节点) = 炉啊_嚏零)

#define 键是否可回收(恩)	(键嚏嚏(恩) & 位_是否可回收)

#define 垃圾回收键(恩)	(键值(恩).垃圾回收)
#define 垃圾回收键恩(恩)	(键是否可回收(恩) ? 垃圾回收键(恩) : NULL)


/*
** 使用一个'零表'来标记表中的死键. 这些键为移除条目保留空间,
*  这可能仍然是链的一部分. 
*  注意'键嚏嚏' 没有 位_是否可回收 集,
*   所以这些值被认为是不可回收的,与任何有效值不同.
*/
#define 设置死键(恩)	(键嚏嚏(恩) = 炉啊_嚏表, 垃圾回收键(恩) = NULL)


/* }================================================================== */



/*
** '模块' 哈希操作 (大小总是2的幂)
*/
#define 嘞余数(丝,大小) \
	(检查_表达式((大小&(大小-1))==0, (投_整数((丝) & ((大小)-1)))))


#define 二到(斯)	(1<<(斯))
#define 大小节点(嚏)	(二到((嚏)->嘞大小节点))


/* '炉啊欧_utf8跳出'函数的缓冲区大小 */
#define UTF8缓冲大小	8

炉啊艾_函 int 炉啊欧_utf8跳出 (char *缓冲, unsigned long 斯);
炉啊艾_函 int 炉啊欧_向上取整log2 (unsigned int 斯);
炉啊艾_函 int 炉啊欧_原始算术 (炉啊_国 *嘞, int 操作, const 嚏值 *匹1,
                             const 嚏值 *匹2, 嚏值 *结果);
炉啊艾_函 void 炉啊欧_算术 (炉啊_国 *嘞, int 操作, const 嚏值 *匹1,
                           const 嚏值 *匹2, 斯嚏颗身份 结果);
炉啊艾_函 size_t 炉啊欧_串到号 (const char *丝, 嚏值 *欧);
炉啊艾_函 int 炉啊欧_十六进制值 (int 西);
炉啊艾_函 void 炉啊欧_到串 (炉啊_国 *嘞, 嚏值 *对象);
炉啊艾_函 const char *炉啊欧_推微弗串 (炉啊_国 *嘞, const char *格式,
                                                       微啊_列表 实参匹);
炉啊艾_函 const char *炉啊欧_推弗串 (炉啊_国 *嘞, const char *格式, ...);
炉啊艾_函 void 炉啊欧_大块身份 (char *出, const char *源码, size_t 源长度);


#endif